import { FileService } from '@app/file';
import { PrismaService } from '@app/prisma';
import { SysTestChapterEntity } from '@app/prisma/sys.test.chapter.entity/sys.test.chapter.entity';
import { SysTestGroupEntity } from '@app/prisma/sys.test.group.entity/sys.test.group.entity';
import { Injectable } from '@nestjs/common';

@Injectable()
export class TestService {
  constructor(
    private readonly file: FileService,
    private readonly prisma: PrismaService
  ) { }
  public GroupAvatarRoot = this.file.make("test_group")
  getGroupAvatarPath(entity: SysTestGroupEntity) {
    return this.file.join(this.GroupAvatarRoot, entity.id.toString() + ".png")
  }

  public TestAvatarRoot = this.file.make("test")
  getTestAvatarPath(entity: SysTestGroupEntity) {
    return this.file.join(this.TestAvatarRoot, entity.id.toString() + ".png")
  }


  /**
   * 获取、管理chapter的资源
   */
  public ChapterFileRoot = this.file.make("chapter_resource")
  public getChapterResourcePath(entity: SysTestChapterEntity) {
    return this.file.join(this.ChapterFileRoot, entity.id.toString())
  }
  public getChapterResource(entity: SysTestChapterEntity, name: string) {
    return this.file.join(this.getChapterResourcePath(entity), name)
  }
  getChapterResourceList(entity: SysTestChapterEntity) {
    return this.file.readdir(this.getChapterResourcePath(entity))
  }

  async createTestGroup(name: string, base64: string, desc?: string, order?: number, status?: boolean) {
    const buffer = this.file.base64_to_buffer(base64)
    const entity = await this.prisma.sys_test_group.create({
      data: {
        name,
        desc,
        order,
        status
      }
    })
    this.file.writeFile(this.getGroupAvatarPath(entity), buffer);
    return entity
  }

  async createTest(name: string, base64: string, sys_test_groupId: number, desc?: string, order?: number, status?: boolean) {
    const buffer = this.file.base64_to_buffer(base64)
    const entity = await this.prisma.sys_test.create({
      data: {
        name,
        desc,
        order,
        status,
        sys_test_groupId
      }
    })
    this.file.writeFile(this.getTestAvatarPath(entity), buffer);
    return entity
  }

  async createTestChapter(sys_testId: number, name: string,
    is_test?: boolean, money?: number, desc?: string,
    order?: number, status?: boolean, PPT?: string,
    PDF?: string, video?: string, one2one?: string, outline?: string) {
    const entity = await this.prisma.sys_test_chapter.create({
      data: {
        name,
        desc,
        order,
        status,
        sys_testId,
        PPT,
        PDF,
        video,
        one2one,
        outline,
        money,
        is_test
      }
    })
    return entity
  }

  async createTestPaper(name: string, sys_test_chapterId: number,
    desc?: string, order?: number, status?: boolean,
    is_free?: boolean, time?: number, score?: number) {
    const entity = await this.prisma.sys_test_paper.create({
      data: {
        name,
        desc,
        order,
        status,
        sys_test_chapterId,
        is_free,
        time,
      }
    })
    return entity
  }
  async createTestByJson(json: string, path: string, sys_test_groupId: number) {
    const data = JSON.parse(json ? json : this.file.readFile(path).toString())
    const questionTypeMap = { "单选题": "SINGLE", "多选题": "MULTIPLE", "判断题": "JUDGE", "程序填空题": "FILL", "编程题": "ANSWER" }
    const res = { test: 0, chapter: 0, paper: 0, question: 0 };
    for (const test of data) {
      const sys_test = await this.prisma.sys_test.findMany({
        where: {
          name: test.name,
          sys_test_groupId
        }
      })
      const sys_test_id = sys_test.length == 1 ? sys_test[0].id :
        (await this.createTest(test.name, test.img, sys_test_groupId, test.desc, test.order, test.status)).id;
      for (const chapter of test.chapters) {
        const sys_test_chapter = await this.prisma.sys_test_chapter.findMany({
          where: {
            name: chapter.name,
            sys_testId: sys_test_id
          }
        })
        const sys_test_chapter_id = sys_test_chapter.length == 1 ?
          sys_test_chapter[0].id :
          (await this.createTestChapter(sys_test_id, chapter.name, chapter.is_test, chapter.money, chapter.desc,
            chapter.order, chapter.status, chapter.PPT, chapter.PDF, chapter.video, chapter.one2one, chapter.outline)).id;
        for (const paper of chapter.papers) {
          const time = paper.time.indexOf("分钟") != -1 ? parseInt(paper.time) : 0
          const sys_test_paper = await this.prisma.sys_test_paper.findMany({
            where: {
              name: paper.name,
              sys_test_chapterId: sys_test_chapter_id
            }
          });
          if (sys_test_paper.length == 1) {
            await this.prisma.sys_test_question.deleteMany({
              where: {
                sys_test_paperId: sys_test_paper[0].id,
                order: {
                  in: paper.problems.map(q => q.order)
                }
              }
            });
          }
          const paperId = sys_test_paper.length == 1 ? sys_test_paper[0].id :
            (await this.createTestPaper(paper.name,
              sys_test_chapter_id, undefined, paper.order, undefined,
              undefined, time, parseInt(paper.total_score))).id;
          for (const question of paper.problems) {
            if (!question.answer) {
              question.answer = "见解析";
            }
            switch (question.type) {
              case "单选题":
                question.answer = JSON.stringify([question.answer]);
                break;
              case "多选题":
                question.answer = JSON.stringify(question.answer.split(''));
                break;
              case "判断题":
                if (question.answer == '正确') question.answer = true;
                else if (question.answer == '错误') question.answer = false;
                question.answer = JSON.stringify([question.answer]);
                break;
              case "程序填空题":
                question.answer = JSON.stringify(question.answer);
                break;
              case "编程题":
                question.answer = question.answer;
                break;
            }
            await this.prisma.sys_test_question.create({
              data: {
                name: question.title,
                type: questionTypeMap[question.type],
                score: parseInt(question.score),
                order: question.order,
                content: JSON.stringify(question.select),
                answer: question.answer,
                help: question.help || "略",
                sys_test_paper: {
                  connect: {
                    id: paperId
                  }
                },
              }
            })
            res.question++
          }
          res.paper++
        }
        res.chapter++
      }
      res.test++
    }
    return [res.test, res.chapter, res.paper, res.question];
  }
}